package com.jkgl.controller;

import com.alibaba.fastjson2.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jkgl.common.core.domain.R;
import com.jkgl.common.core.domain.entity.SysUser;
import com.jkgl.entity.UserInfoDayEntity;
import com.jkgl.entity.UserInfoSelfEntity;
import com.jkgl.model.result.SelfUserVO;
import com.jkgl.service.UserInfoDayService;
import com.jkgl.service.UserInfoSelfService;
import com.jkgl.system.service.ISysUserService;
import io.swagger.annotations.ApiOperation;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.SetOperations;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.time.LocalDate;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@Slf4j
@RequestMapping("dataShow")
@RequiredArgsConstructor
public class AdminDataShowController {
    private final UserInfoDayService userInfoDayService;
    private final UserInfoSelfService userInfoSelfService;
    private final ISysUserService sysUserService;
    private final RedisTemplate redisTemplate;


    @GetMapping("UserTrend/{days}")
    @ApiOperation("用户增长趋势 总/每天增长量")
    public R userTrend(@PathVariable Integer days){
        LocalDate startTime = LocalDate.now().plusDays(1);
        QueryWrapper<SysUser> userQuery = new QueryWrapper<>();
        Map<String, Long> map =new HashMap<>();
        for(int i = days;i>=0;i--){
            startTime = startTime.minusDays(1);
            userQuery.clear();
            userQuery.lambda().ge(SysUser::getCreateTime,startTime)
                    .le(SysUser::getCreateTime,startTime.plusDays(1));
            long count = sysUserService.count(userQuery);
            map.put(startTime.toString(),count);
        }
        userQuery.clear();
//        起始时间
        userQuery.lambda().lt(SysUser::getCreateTime,startTime);
        long count = sysUserService.count(userQuery);
        JSONObject json = new JSONObject();
        json.put("count",count);
        json.put("map",map);
        return R.ok(json);
    }


        @GetMapping("BasicInfomation")
    @ApiOperation("基本信息-简单直接输出的信息")
    public R basicInformation(){
        LocalDate now = LocalDate.now();
        Long today = redisTemplate.opsForSet().size("login:count:" + now);
        Long yesterday = redisTemplate.opsForSet().size("login:count:"+ now.minusDays(1));
        JSONObject activeData = new JSONObject();
        activeData.put("today",today);
        activeData.put("yesterday",yesterday);
        QueryWrapper<UserInfoDayEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(UserInfoDayEntity::getCreateTime,now);
        List<UserInfoDayEntity> todays = userInfoDayService.list(queryWrapper);
        double toSum = todays.stream().filter(e -> e.getSportTimeLong() != null).mapToDouble(UserInfoDayEntity::getSportTimeLong).sum();
        queryWrapper.clear();
        queryWrapper.lambda().eq(UserInfoDayEntity::getCreateTime,now.minusDays(1));
        List<UserInfoDayEntity> yesterdays = userInfoDayService.list(queryWrapper);
        double yesSum = yesterdays.stream().filter(e -> e.getSportTimeLong() != null).mapToDouble(UserInfoDayEntity::getSportTimeLong).sum();
        JSONObject sportTime = new JSONObject();
        sportTime.put("today",toSum/todays.size());
        sportTime.put("yesterday",yesSum/yesterdays.size());
        JSONObject result = new JSONObject();
        result.put("acitve",activeData);
        result.put("sprotTime",sportTime);
        return R.ok(result);
    }


    @GetMapping("TotalByBMI")
    @ApiOperation("BMI 统计图表")
    public R totalByBMI(Integer minAge,Integer maxAge){
        //最好连表查 四条数据  group by
//        算了 都拿出来对比  上面不好实现
        long n_low = 0;
        long v_low = 0;
        long n_mid = 0;
        long v_mid = 0;
        long n_fat = 0;
        long v_fat = 0;
        long n_tfat = 0;
        long v_tfat = 0;
       List<SelfUserVO> vos = userInfoSelfService.getBMIAll(minAge,maxAge);
        n_low = vos.stream().filter(e -> Double.parseDouble(e.getBmi())<18.5 && "0".equals(e.getSex())).count();
        v_low = vos.stream().filter(e -> Double.parseDouble(e.getBmi())<18.5 && "1".equals(e.getSex())).count();
        n_mid = vos.stream().filter(e -> Double.parseDouble(e.getBmi())>=15 && Double.parseDouble(e.getBmi())<24 && "0".equals(e.getSex())).count();
        v_mid = vos.stream().filter(e -> Double.parseDouble(e.getBmi())>=15 && Double.parseDouble(e.getBmi())<24 && "1".equals(e.getSex())).count();
        n_fat = vos.stream().filter(e -> Double.parseDouble(e.getBmi())>=24 && Double.parseDouble(e.getBmi())<28 && "0".equals(e.getSex())).count();
        v_fat = vos.stream().filter(e -> Double.parseDouble(e.getBmi())>=24 && Double.parseDouble(e.getBmi())<28 && "1".equals(e.getSex())).count();
        n_tfat = vos.stream().filter(e -> Double.parseDouble(e.getBmi())>=28 && "0".equals(e.getSex())).count();
        v_tfat = vos.stream().filter(e -> Double.parseDouble(e.getBmi())>=28 && "1".equals(e.getSex())).count();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("n_low",n_low);
        jsonObject.put("v_low",v_low);
        jsonObject.put("n_mid",n_mid);
        jsonObject.put("v_mid",v_mid);
        jsonObject.put("n_fat",n_fat);
        jsonObject.put("v_fat",v_fat);
        jsonObject.put("n_tfat",n_tfat);
        jsonObject.put("v_tfat",v_tfat);
        return R.ok(jsonObject);
    }


    @GetMapping("SportGoal")
    @ApiOperation("运动达成度")
    public R sportGoal(Integer minAge,Integer maxAge){
        long n_sport = 0;
        long v_sport = 0;
        long n_un_sport = 0;
        long v_un_sport = 0;
        List<SelfUserVO> vos = userInfoDayService.getSportGoal(minAge,maxAge);
        n_sport = vos.stream().filter(e -> e.getSportTimeLong() >= e.getExerciseMinutesGoal() && "0".equals(e.getSex())).count();
        v_sport = vos.stream().filter(e -> e.getSportTimeLong() >= e.getExerciseMinutesGoal() && "1".equals(e.getSex())).count();
        n_un_sport = vos.stream().filter(e -> e.getSportTimeLong() < e.getExerciseMinutesGoal() && "0".equals(e.getSex())).count();
        v_un_sport = vos.stream().filter(e -> e.getSportTimeLong() < e.getExerciseMinutesGoal() && "1".equals(e.getSex())).count();
        JSONObject sportTime = new JSONObject();
        sportTime.put("n_sport",n_sport);
        sportTime.put("v_sport",v_sport);
        sportTime.put("n_un_sport",n_un_sport);
        sportTime.put("v_un_sport",v_un_sport);

        long n_step = 0;
        long v_step = 0;
        long n_un_step = 0;
        long v_un_step = 0;
        n_step = vos.stream().filter(e -> Integer.parseInt(e.getStepNumber()) >= Integer.parseInt(e.getTargetStep()) && "0".equals(e.getSex())).count();
        v_step = vos.stream().filter(e -> Integer.parseInt(e.getStepNumber()) >= Integer.parseInt(e.getTargetStep()) && "1".equals(e.getSex())).count();
        n_un_step = vos.stream().filter(e -> Integer.parseInt(e.getStepNumber()) < Integer.parseInt(e.getTargetStep()) && "0".equals(e.getSex())).count();
        v_un_step = vos.stream().filter(e -> Integer.parseInt(e.getStepNumber()) < Integer.parseInt(e.getTargetStep()) && "1".equals(e.getSex())).count();
        JSONObject step = new JSONObject();
        step.put("n_step",n_step);
        step.put("v_step",v_step);
        step.put("n_un_step",n_un_step);
        step.put("v_un_step",v_un_step);
        JSONObject result = new JSONObject();
        result.put("step",step);
        result.put("sportTime",sportTime);
        return R.ok(result);
    }


    @GetMapping("UserLoginNum")
    @ApiOperation("七天用户登录数折线")
    public R userLoginNum(){
        LocalDate now = LocalDate.now();
        Map<String, Long> map = new HashMap<>();
        SetOperations setOperations = redisTemplate.opsForSet();
        for(int i =0; i<7;i++){
            Long size = setOperations.size("login:count:" + now);
            map.put(now.toString(),map.getOrDefault(now.toString(),0L) + size);
            now = now.minusDays(1);
        }
        return R.ok(map);
    }

}
